package com.realestate.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.realestate.common.SpringContext;

/**
 * This class is the base dao class. All Other dao classes needs to extend this
 * @author Srivatsan
 *
 * @param <E> (Entity class)
 * @param <PK> Primary Key Datatype (Integer, Long,String etc)
 */
public abstract class BaseDAO<E, PK extends Serializable>  {
	
	private HibernateTemplate hbmTemplate;
	private String hibernateTemplate ="hbmTemplate" ;
	/**
	 * @return the hbmTemplate
	 */
	public HibernateTemplate getHbmTemplate() {
		if(hbmTemplate==null){
			return (HibernateTemplate) SpringContext.getBean(hibernateTemplate);
		}
		return hbmTemplate;
	}

	/**
	 * @param hbmTemplate the hbmTemplate to set
	 */
	public void setHbmTemplate(HibernateTemplate hbmTemplate) {
		this.hbmTemplate = hbmTemplate;
	}


	/**
	 * @param newInstance
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public PK save(E newInstance) {
		return (PK) getHbmTemplate().save(newInstance);
	}

	
	/**
	 * @param id
	 * @return
	 */
	public E findById(PK id) {
		return (E) getHbmTemplate().get(getEntityClass(), id);
	}

	/**
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<E> findAll() {
		return getHbmTemplate().findByCriteria(createDetachedCriteria());
	}

	/**
	 * @param propertyName
	 * @param value
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<E> findAllByProperty(String propertyName, Object value) {
		DetachedCriteria criteria = createDetachedCriteria();
		criteria.add(Restrictions.eq(propertyName, value));
		return getHbmTemplate().findByCriteria(criteria);
	}

	/**
	 * @param object
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<E> findByExample(E object) {
		List<E> resultList = getHbmTemplate().findByExample(object, 0, 1);
		return resultList;
	}

	/**
	 * @param object
	 * @param firstResult
	 * @param maxResults
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<E> findByExample(E object, int firstResult, int maxResults) {
		List<E> resultList = getHbmTemplate().findByExample(object,
				firstResult, maxResults);
		return resultList;
	}

	/**
	 * @param transientObject
	 */
	public void update(E transientObject) {
		getHbmTemplate().update(transientObject);
	}

	/**
	 * @param transientObject
	 */
	public void saveOrUpdate(E transientObject) {
		getHbmTemplate().saveOrUpdate(transientObject);
	}

	/**
	 * @param persistentObject
	 */
	public void delete(E persistentObject) {
		getHbmTemplate().delete(persistentObject);
	}

	/**
	 * @return
	 */
	protected abstract Class<E> getEntityClass();

	/**
	 * @return
	 */
	protected DetachedCriteria createDetachedCriteria() {
		return DetachedCriteria.forClass(getEntityClass());
	}
}